1 /** 2 The following examples come from 3 $(LINK http://zetcode.com/db/sqlite/constraints/). 4 Even though it is a SQLite tutorial the point is to show how to use this package 5 which does not have to be just SQLite. 6 */ 7 module test.examples_unique_constraint; 8 9 version(D_Ddoc) 10 { 11 /// 12 class BlankClassSoDocsWillBeGenerated { } 13 } 14 15 16 /** 17 This example is for the UNIQUE constraint and the PRIMARY KEY constraint. 18 The table in SQL can be created by 19 $(D $(D $(D sql 20 CREATE TABLE Brands 21 ( 22 Id INTEGER NOT NULL PRIMARY KEY, 23 BrandName TEXT UNIQUE 24 ); 25 26 ))) 27 28 Any column marked with @PrimaryKeyColumn must also have @NotNull. Unlike SQLite, 29 if a column is marked as int and @PrimaryKeyColumn it is not auto-incremented. 30 */ 31 unittest 32 { 33 import db_constraints; 34 35 class Brand 36 { 37 private int _Id; 38 // marking Id with not null and primary key 39 @NotNull @PrimaryKeyColumn 40 @property int Id() 41 { 42 return _Id; 43 } 44 @property void Id(int value) 45 { 46 setter(_Id, value); 47 } 48 49 private string _BrandName; 50 // marking BrandName with UniqueConstraintColumn 51 // so the collection will know this property should be 52 // unique for all records 53 @UniqueConstraintColumn!("Unique") 54 @property string BrandName() 55 { 56 return _BrandName; 57 } 58 @property void BrandName(string value) 59 { 60 setter(_BrandName, value); 61 } 62 63 this(int Id_, string BrandName_) 64 { 65 this._Id = Id_; 66 this._BrandName = BrandName_; 67 // do not forget to initialize the keyed item! 68 initializeKeyedItem(); 69 } 70 71 // do not forget to add in the keyed item! 72 mixin KeyedItem!(); 73 } 74 75 // this is what I call the plural class 76 // or table class. This is the collection 77 // of rows (in this example Brands). 78 class Brands 79 { 80 // this mixin already does the 81 // initializations and every method 82 // I want for this tutorial so I 83 // do not need anything else. 84 mixin KeyedCollection!(Brand); 85 } 86 87 import std.exception : assertNotThrown, assertThrown; 88 89 // UNIQUE constraint 90 { 91 // we can start by putting two records into the collection. 92 // now brands holds a record for Coca Cola and Pepsi 93 auto brands = new Brands([new Brand(1, "Coca Cola"), 94 new Brand(2, "Pepsi")]); 95 96 auto anotherPepsi = new Brand(3, "Pepsi"); 97 // if we try to add another record that has Pepsi for 98 // the brand name we will get a unique constraint exception 99 assertThrown!UniqueConstraintException(brands.add(anotherPepsi)); 100 101 // we can see if the new record will violate any unique constraints 102 // before we add it to the collection by using violatesUniqueConstraints 103 assert(brands.violatesUniqueConstraints(anotherPepsi)); 104 } 105 106 // PRIMARY KEY constraint 107 { 108 // the primary key is unique and not null 109 // by default we can use the primary key to look up 110 // records in the collection 111 auto brands = new Brands([new Brand(1, "Coca Cola"), 112 new Brand(2, "Pepsi")]); 113 114 // since Pepsi's Id is the primary key we can use 2 to find pepsi 115 assert(brands[2].BrandName == "Pepsi"); 116 assert(brands[2].Id == 2); 117 // this is because brands is really an associative array that uses the 118 // primary key in this case as the AA key. We can check if the 119 // collection already contains a primary key of 2 by using contains 120 assert(brands.contains(2)); 121 // and does not contain 4 122 assert(!brands.contains(4)); 123 // if you try to get an item that is not there you will get an exception 124 assertThrown!KeyedException(brands[4].BrandName); 125 126 // lets add two more records 127 brands ~= [new Brand(3, "Sun"), new Brand(4, "Oracle")]; 128 129 // now it does contain 4 130 assert(brands.contains(4)); 131 assertNotThrown!KeyedException(brands[4].BrandName); 132 } 133 }